<?php
// +----------------------------------------------------------------------
// | TYCMS [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2015-2016 http://www.rainfer.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: aliang <461321026@qq.com>
// +----------------------------------------------------------------------
namespace app\home\controller;

use think\Db;
use Payment\ChargeContext;
use Payment\Config;
use Payment\Common\PayException;

use Payment\NotifyContext;

class Payment extends Base
{
	public function index()
    {
		return $this->view->fetch('user:payment');
	}
	
	//支付订单
	public function payorder(){
	    $id  = input('id/d');	
	    if($id <= 0)
	        $this->error('不存在该订单！');
	    
	    $uid = session('hid');
	    if(intval($uid) == 0)
	        $this->error('请登录用户再支付！',url('home/login/index').'?reffer='.url('home/payment/payorder',['id'=>$id]));
	    
	    $orders = Db::name("goods_order")->where("id",$id)->find();
	    if(empty($orders))
	        $this->error('不存在该订单！');
	    if($orders['state_pay'] < 0)
	        $this->error('该订单已取消支付！');
	    if($orders['state_pay'] == 2)
	        $this->error('该订单已完成付款！');
	    if($orders['state_trade'] < 0)
	        $this->error('该订单交易已取消！');
	     
	    $charge = new ChargeContext();
	    $time = time();
	    $payment_model = Db::name("payment");
	    $out_trade_no  = $charge->createPayid();
	    $money         = $orders['total_fee'];
	    $paytype       = empty($orders['pay_type']) ? 'alipay':$orders['pay_type'];
	    if($orders['order_type']==2){
	       $goods  = Db::name("goods")->where("id",$orders['gid'])->find();
	       $product_name  = !empty($goods['goods_title']) ? $goods['goods_title']:"";
	    }else{
	       $product_name  = $orders['subject'];
	    }
	    $user = Db::name("member_list")->find($uid);
	    if($paytype == 'money'){//余额支付
	       if($user['money'] < $money){
	          $this->error('您的余额不足，不能完成本次支付！',url('home/center/chongzhi'));
	       }else{
	          //step 1 扣费 写日志
	          $param = [
	              'uid'     =>$uid,
	              'isadd'   =>false,
	              'fee'     =>$money,
	              'title'   => ($orders['order_type']==2 ? "购买".$product_name."({$orders['number']}件)":$product_name)."，支付费用，共计({$money}元)",
	              'order_id'=>$orders['id'],
	              'content' =>"用户余额支付，".($orders['order_type']==2 ? "购买产品[{$product_name}]({$orders['number']}件)":$product_name).",花费{$money}元",
	          ];
	          $res = add_member_log($param);
	          if($res['code'] == 0)
	             $this->error($res['msg'],url('home/center/orderlist'));
	          
	          //step 2 修改订单状态
	          Db::name("goods_order")->where('id',$orders['id'])->update(['state_pay'=>2,'state_trade'=>2]);
	          //升级
	          if($orders["order_type"] == 3){
	              Db::name("goods_order")->where('id',$orders['id'])->setField('state_trade',9);
	              Db::name("member_list")->where(['member_list_id'=>$user["member_list_id"]])->setfield("member_list_groupid",$orders["gid"]);  
	              $this->success('恭喜您已成功升级！您将拥有更多特权和优惠！',url('home/center/vieworder',['id'=>$id]));
	          }else{
	              $this->success($res['msg'],url('home/center/vieworder',['id'=>$id]));
	          }
	          //step 3往上级返点   确认收货再做操作
	          //$res = update_fencheng($orders['id']);
	          //if($res['code'] == 0){
	          //   $this->error($res['msg'],url('home/center/orderlist'));
	          //}else{
	          //   $this->sccuess($res['msg'],url('home/center/orderlist'));
	          //}
	       }
	    }
	     
	    
	    $product_body  = '在线订单提交（'.date('Y-m-d H:i:s').'）,商品：'.$product_name;
	    $pay_config    = config("payment.{$paytype}");
	   
	    if(empty($pay_config['display']))
	        $this->error('支付方式未开启或未配置!!');

	    if(!$money || !$paytype)
	        $this->error('订单参数错误,获取不完整!!');

	    $sl_data = array(
	        'out_trade_no' => $out_trade_no,
	        'pay_trade_no' => $out_trade_no,//$orders['sn'],
	        'money'        => $money,
	        'status'       => 0,
	        'type'         => $paytype,
	        'uid'          => $orders['uid'],
	        'create_time'  => $time,
	        'update_time'  => $time,
	        'client_ip'    => request()->ip(),
	        'product_name' => $product_name,
	        'product_body' => $product_body,
	        'oid'          => $id,
	    );
	    if($orders['order_type'] == 1){//用户充值类型
	        $extra_param = [
	            'uid'   =>$orders['uid'],
	            'method'=>'add_money',
	            'money' =>$orders['total_fee']
	        ];
	        $sl_data['extra_param'] = serialize($extra_param);
	    }
	    if($orders['order_type']==2){
	        $sl_data['product_url'] = url('home/shop/show',['id'=>$orders['gid']]);
	    }
 
	    $rst = Db::name("payment")->insertGetId($sl_data);
	    
	    
// 	    $pinfo = Db::name("payment")->where('oid',$id)->find();
// 	    if(!empty($pinfo)){
// 	       $rst = Db::name("payment")->insertGetId($sl_data);
// 	    }else{
// 	       $rst = Db::name("payment")->where('oid',$id)->update($sl_data);
// 	    }
 
	    if($rst){
	        $url = '/home/payment/dopay?out_trade_no='.$out_trade_no.'&sign='.md5($out_trade_no.request()->ip());
	        $this->redirect($url);
	        //$this->dopay($param['out_trade_no'],$param['sign']);
	        $param = [
	            'out_trade_no'=>$out_trade_no,
	            'sign' => md5($out_trade_no.request()->ip()),
	        ];
	        $url   = url('/home/payment/dopay',$param);
	        $return_data = array(
	            'code'=>'SUCCESS',
	            'paytype'=>$paytype,
	            'info'=>'生成订单成功,准备跳转支付页面!!','url'=>$url
	        );
	        return $return_data;
	    }
	     
	    
	}
	
	public function runpay()
    {
		if (!request()->isAjax()){
			$this->error('提交方式不正确',url('home/payment/index'));
		}else{
			$charge = new ChargeContext();
			$time = time();
			$payment_model=Db::name("payment");
			$out_trade_no = $charge->createPayid();
            $money = input('coins'); 
            $paytype = input('pay_type');
            $product_name = input('product_name');
            $product_body = input('product_body');
            $pay_config = config("payment.{$paytype}");
            if(empty($pay_config['display'])){
                $return_data = array('coode'=>'eroor','info'=>'支付方式未开启或未配置!!');
                return $return_data;
                exit();
            }
            if(!$money || !$paytype){
                $return_data = array('coode'=>'eroor','info'=>'订单参数错误,获取不完整!!');
                return $return_data;
                exit();
            }
			$sl_data = array(
				'out_trade_no' => $out_trade_no,
				'money'        => $money,
				'status'       => 0,
				'type'         => $paytype,
				'uid'          => 1,
				'create_time'  => $time,
				'update_time'  => $time,
				'client_ip'    => request()->ip(),
				'product_name' => $product_name,
				'product_body' => $product_body
				);
			$rst=$payment_model->insertGetId($sl_data);
			if($rst){
			     
				//$this->redirect('home/payment/dopay',array('out_trade_no'=>$out_trade_no,'sign'=>md5($out_trade_no.request()->ip())));
                $url = '/home/payment/dopay?out_trade_no='.$out_trade_no.'&sign='.md5($out_trade_no.request()->ip());
                $return_data = array('code'=>'SUCCESS','paytype'=>$paytype,'info'=>'生成订单成功,准备跳转支付页面!!','url'=>$url
                    );
                return $return_data;
			}


		}
	}
	public function dopay($out_trade_no='NULL',$sign='NULL')
    {
        header("Content-type: text/html; charset=utf-8");
        
		if(!$out_trade_no || !$sign || $sign!==md5($out_trade_no.request()->ip())){echo 'error sgin!!';exit();}
		$payment_model=Db::name("payment");
		$pay_info = $payment_model->where(array("out_trade_no"=>$out_trade_no,"status"=>0))->find();
		if($pay_info){
			$pay_type = $pay_info['type'];
			$pay_config = config("payment.{$pay_type}");
			$payData = [
                "order_no"      => $pay_info['out_trade_no'],
                "amount"        => $pay_info['money'],// 单位为元 ,最小为0.01
                "client_ip"     => $pay_info['client_ip'],
                "subject"       => $pay_info['product_name'],
                "body"          => $pay_info['product_body'],
                "show_url"      => $pay_info['product_url'],// 支付宝手机网站支付接口 该参数必须上传 。其他接口忽略
                "extra_param"   => $pay_info['extra_param'],
            ]; 
			 
            $payData['product_id']  = $pay_info['oid'] > 0 ? $pay_info['oid']:'123456';
            //获取OPENID 
            // TODO 暂时先用COOKE之后改查数据表
            if($pay_type=='wxpaypub' || $pay_type=='wxpayapp'){
                $openid=isset($_COOKIE['openid'])?$_COOKIE['openid']:'';
                if(empty($openid)){
                    $url = 'http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"]; 
                    //绑定要设定cookie  setcookie('openid',$openid,time()+86400*30);  
                    $this->redirect('home/Oauth/bang',array('type'=>'Wechat','redirect'=>$url));  
                }else{
                $payData['openid']=$openid;
                }              
            }
            //获取OPENID结束
            $charge = new ChargeContext();
            try {
            	switch ($pay_type){
            	        case 'aliwappay':  
            	        $type = Config::ALI_CHANNEL_WAP;
                        break;
                        case 'alipay':
                        $type = Config::ALI_CHANNEL_WEB;
                        break;
                        case 'alipayapp':
                        $type = Config::ALI_CHANNEL_APP;
                        break;
                        case 'wxpayqrcode':
                        $type = Config::WX_CHANNEL_QR;
                        break;
                        case 'wxpayapp':
                        $type = Config::WX_CHANNEL_APP;
                        break;
                        case 'wxpaypub':
                        $type = Config::WX_CHANNEL_PUB;
                        break;
            }
                $charge->initCharge($type, $pay_config);
                $ret = $charge->charge($payData);
               } catch (PayException $e) {
            echo $e->errorMessage();exit;
            }
            if ($type === Config::ALI_CHANNEL_APP) {   //阿里app支付
                var_dump($ret);
                } elseif ($type === Config::WX_CHANNEL_QR) {  //微信QRCODE支付
                $url = urlencode($ret);
                $pay_qrcode_url = "http://paysdk.weixin.qq.com/example/qrcode.php?data={$url}";
                $this->assign('pay_qrcode_url',$pay_qrcode_url);
                $this->assign('out_trade_no',$pay_info['out_trade_no']); //amount
                $this->assign('money',$pay_info['money']);
                $this->assign('sgin',$sign);
                $this->assign('brower',x_get_browser());
                return $this->view->fetch('payment:wxqrcode');
                } elseif ($type === Config::WX_CHANNEL_PUB) {  //微信JSAPI
                $json = $ret;
                $this->assign('json',$json);
                return $this->view->fetch('payment:wxpaypub');
                //var_dump($json);
                } elseif (stripos($type, 'wx') !== false) {  //微信app支付
                var_dump($ret);
                } elseif (stripos($type, 'ali') !== false) {
                // 跳转支付宝
                header("Location:{$ret}");
            }

		}else{
			$this->error('订单不合法验证失败',url('home/center/orderlist'));exit;
		}

	}
	
	public function pay_check(){
	    $out_trade_no = input('request.out_trade_no/s');
	    $oInfo        = Db::name('payment')->where("out_trade_no",$out_trade_no)->find();
	    if(!empty($oInfo) && $oInfo['oid'] > 0){
	       $url =  url('home/center/vieworder',['id'=>$oInfo['oid']]) ;
	       if($oInfo['status'] == 1){
	          return json(['code'=>1,'msg'=>'该订单支付成功！','url'=>$url]);
	       }else{ 
	          return json(['code'=>0,'msg'=>'该订单待支付！','url'=>$url]);
	       }
	   }
	   return json(['code'=>-1,'msg'=>'该订单错误！','url'=>url('home/center/orderlist')]);
	}
    
    /*支付成功-跳转页面*/
    public function pay_success()
    {
        $out_trade_no = input('get.out_trade_no/s');
        $oInfo        = Db::name('payment')->where("out_trade_no",$out_trade_no)->find();
        if(empty($oInfo)){
           $this->error('订单信息错误！',url('home/center/orderlist')); 
        }else{
           if($oInfo['oid'] > 0){
              $url =  url('home/center/vieworder',['id'=>$oInfo['oid']]) ;
              if($oInfo['status'] == 1){
                  $this->success('支付完成',$url);
              }else{
                  $this->error('订单未能支付成功！请在我的订单列表继续操作付款！！',$url);
              } 
           } 
           $this->error('订单信息错误！',url('home/center/orderlist'));
        }
   
    }

	public function wxqrcodequery($out_trade_no='NULL',$sgin='NULL')
    {
        if(!$out_trade_no || !$sgin || $sgin!==md5($out_trade_no.request()->ip())){echo 'error sgin!!';exit();}
        $payment_model=Db::name("payment");
        $pay_info = $payment_model->where(array("out_trade_no"=>$out_trade_no))->find();
        $data = array('status'=>$pay_info['status']);
        return $data;
	}

    public function wxqrcode_notify_url()
    {
        $notify = new NotifyContext();
        $callback = new PaymentNotify();
        $pay_config = config("payment.wxpayqrcode");
        try {
            $notify->initNotify(Config::WEIXIN, $pay_config);
            $ret  = $notify->notify($callback);
            $data = @file_get_contents('php://input');
            $data = $this->xml_to_array($data);
            $ret  =  $this->xml_to_array($ret);
            if($ret['return_code'] == 'SUCCESS'){
                $out_trade_no     = $data['out_trade_no'];
                if(!empty($out_trade_no))
                    update_user_order($out_trade_no);
            }
           } catch (PayException $e) {
        echo $e->errorMessage();exit;
        }
    }

    public function wxpub_notify_url()
    {
        $notify = new NotifyContext();
        $callback = new PaymentNotify();
        $pay_config = config("payment.wxpaypub");
        try {
            $notify->initNotify(Config::WEIXIN, $pay_config);
            $ret = $notify->notify($callback);
        $data = @file_get_contents('php://input');
            $data = $this->xml_to_array($data);
            $ret  =  $this->xml_to_array($ret);
            if($ret['return_code'] == 'SUCCESS'){
                $out_trade_no     = $data['out_trade_no'];
                if(!empty($out_trade_no))
                    update_user_order($out_trade_no);
            }
           } catch (PayException $e) {
        echo $e->errorMessage();exit;
        }
    }

    public function ali_notify_url()
    {
        $notify     = new NotifyContext();
        $callback   = new PaymentNotify();
        $pay_config = config("payment.alipay");
        try {
            $notify->initNotify(Config::ALI, $pay_config);
            $ret = $notify->notify($callback);
            if($ret == 'success'){
               $out_trade_no     = input('out_trade_no');
               $trade_status     = input('trade_status');
               if(!empty($out_trade_no) && $trade_status =='TRADE_SUCCESS')
                   update_user_order($out_trade_no);
            }
        } catch (PayException $e) {
            echo $e->errorMessage();exit;
        }
    }

    public function aliwap_notify_url()
    {
        $notify = new NotifyContext();
        $callback = new PaymentNotify();
        $pay_config = config("payment.alipay");
        try {
            $notify->initNotify(Config::ALI, $pay_config);
            $ret = $notify->notify($callback);
            if($ret == 'success'){
                $out_trade_no     = input('out_trade_no');
                $trade_status     = input('trade_status');
                if(empty($out_trade_no) && $trade_status =='TRADE_SUCCESS')
                    update_user_order($out_trade_no);
            }
           } catch (PayException $e) {
        echo $e->errorMessage();exit;
        }
    }

    function xml_to_array($xml) {
        libxml_disable_entity_loader(true);
        $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
        $val = json_decode(json_encode($xmlstring),true);
        return $val;
    }
	
}